﻿using Common.Core.Cache;
using Common.Core.Enums;
using Common.Core.Extensions;

namespace Common.Helpers
{
    /// <summary>
    /// 订单流水号生成类。
    /// 此类生成方法是日期+递增。递增流水需要设置codeLength，不够位数前面补零。
    /// </summary>
    public sealed class IdentityCodeRedis
    {
        private static readonly object LockObject = new object();

        /// <summary>
        /// IdentityNoRedisGenerator的静态实例
        /// </summary>
        private volatile static IdentityCodeRedis _ig;
        public static IdentityCodeRedis Instance()
        {
            if (_ig == null)
            {
                lock (LockObject)
                {
                    if (_ig == null)
                    {
                        _ig = new IdentityCodeRedis();
                    }
                }
            }
            return _ig;
        }

        /// <summary>
        /// 计算一个Id
        /// </summary>
        /// <param name="codeType">生成订单编号类型</param>
        /// <param name="noType">单子类型，用于缓存Key，避免重复生成</param>
        /// <param name="codeLength">递增编号长度</param>
        /// <returns></returns>
        public long GetIdentity(IdentityCodeType codeType, string noType = "", int codeLength = 5)
        {
            return getIdentityRedis(codeType, codeLength, noType);
        }

        /// <summary>
        /// 计算一个Id
        /// </summary>
        /// <param name="prefix">前缀</param>
        /// <param name="codeType">生成订单编号类型</param>
        /// <param name="noType">单子类型，用于缓存Key，避免重复生成</param>
        /// <param name="codeLength">递增编号长度</param>
        /// <returns></returns>
        public string GetIdentity(string prefix, IdentityCodeType codeType, string noType = "", int codeLength = 5)
        {
            return prefix + getIdentityRedis(codeType, codeLength, noType);
        }

        /// <summary>
        /// 计算一个Id
        /// </summary>
        /// <param name="codeType">生成订单编号类型</param>
        /// <param name="codeLength">递增编号长度</param>
        /// <param name="noType">单子类型，用于缓存Key，避免重复生成</param>
        /// <returns></returns>
        private long getIdentityRedis(IdentityCodeType codeType, int codeLength, string noType)
        {
            string middleCode = "";
            long cacheSeconds = 0;
            switch (codeType)
            {
                case IdentityCodeType.YYYYMMDD:
                    middleCode = DateTime.Now.ToString("yyyyMMdd");
                    cacheSeconds = (24 * 60 * 60) + 5;
                    break;
                case IdentityCodeType.YYMMDD:
                    middleCode = DateTime.Now.ToString("yyMMdd");
                    cacheSeconds = (24 * 60 * 60) + 5;
                    break;
                default:
                    middleCode = DateTime.Now.ToString("yyyyMMdd");
                    cacheSeconds = (24 * 60 * 60) + 5;
                    break;
            }

            // 设置缓存键值
            string cachekey = "MyClassLibraryCommon:IdentityCodeRedis";
            if (noType.IsNotNullAndEmpty())
            {
                cachekey += $":{noType}";
            }
            cachekey += $":{middleCode}";

            // 记录最后一个计数器值
            long _lastEndNo = new CacheHelper().StringIncrement(cachekey, 1, TimeSpan.FromSeconds(cacheSeconds)).ToLong();

            return (middleCode + _lastEndNo.ToString().PadLeft(codeLength, '0')).ToLong();
        }
    }
}